package po.entity;

import po.exception.InvalidNodeCalException;
import po.utils.ParamValueHandler;
import po.enums.Operator;
import po.enums.ParamValueType;
import po.enums.RuleType;
import po.tree.Node;
import po.tree.ResultNode;

import java.util.List;

/**
 * Created by guowei on 2019/6/9.
 */
public class Indicator implements Operatable {
    private String ID;
    private String name;
    private ParamValue value;
    private RuleType type;
    private Node self;

    public Indicator(String ID, String name, ParamValueType type, List<String> valueEnum, double max, double min) {
        this.ID = ID;
        this.name = name;
        this.type = RuleType.INDICATOR;
        this.value = new ParamValue(type, valueEnum, max, min);
    }

    @Override
    public RuleType getType() {
        return this.type;
    }

    @Override
    public void setNode(Node node) {
        this.self = node;
    }

    @Override
    public Node getNode() {
        return self;
    }

    // operate will compact param-ResultNode with current Indicator value
    public void operate(ResultNode rn, Operator operator) throws Exception {
        if(rn == null) {
            throw new NullPointerException("current calculating ResultNode is null");
        }
        if(operator.equals(Operator.DEFAULT) && (rn.getIndicators().size() != 0 || rn.getIndicators().size() != 0)) {
            throw new InvalidNodeCalException();
        }
        // the operator can only be `AND` or `OR`, so the logic are both add current Indicator to ResultNode
        // detailed calculation is done in `checkParamValueCompatible` method
        if(!rn.getIndicators().containsKey(this.getID())){
            rn.putIndicator(this);
        } else {
            Indicator modified  = rn.getIndicators().get(this.getID());
            ParamValue pvRN = modified.getValue();
            ParamValue pvResult = ParamValueHandler.checkParamValueCompatible(pvRN, this.getValue(), operator);
            modified.setValue(pvResult);
            rn.putIndicator(modified);
        }
    }

    public String getID() {
        return ID;
    }

    public String getName() {
        return name;
    }

    public ParamValue getValue() {
        return value;
    }

    public void setValue(ParamValue value) {
        this.value = value;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("PARAM<ID: ");
        sb.append(this.ID);
        sb.append(", Name: ");
        sb.append(this.name);
        sb.append(", RuleType: ");
        sb.append(this.type);
        sb.append(", ParamValue: ");
        sb.append(this.value.toString());
        sb.append(">");
        return sb.toString();
    }
}
